package org.dromara.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.system.domain.SysFaultInfo;
import org.dromara.system.domain.bo.SysFaultInfoBo;
import org.dromara.system.domain.bo.SysFaultInfoQueryBo;
import org.dromara.system.domain.bo.SysFaultManageBo;
import org.dromara.system.domain.vo.SysFaultInfoVo;
import org.dromara.system.domain.vo.SysSolutionDocVo;
import org.dromara.system.mapper.SysFaultInfoMapper;
import org.dromara.system.service.ISysFaultInfoService;
import org.dromara.system.service.ISysSolutionDocService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 故障信息Service业务层处理
 *
 * @author system
 */
@RequiredArgsConstructor
@Service
public class SysFaultInfoServiceImpl implements ISysFaultInfoService {

    private final SysFaultInfoMapper baseMapper;
    private final ISysSolutionDocService solutionDocService;

    /**
     * 查询故障信息列表
     *
     * @param queryBo   查询参数
     * @param pageQuery 分页参数
     * @return 故障信息分页列表
     */
    @Override
    public TableDataInfo<SysFaultInfoVo> queryPageList(SysFaultInfoQueryBo queryBo, PageQuery pageQuery) {
        LambdaQueryWrapper<SysFaultInfo> lqw = buildQueryWrapper(queryBo);
        Page<SysFaultInfoVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    private LambdaQueryWrapper<SysFaultInfo> buildQueryWrapper(SysFaultInfoQueryBo queryBo) {
        LambdaQueryWrapper<SysFaultInfo> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(queryBo.getExcavatorModel()), SysFaultInfo::getExcavatorModel, queryBo.getExcavatorModel());
        lqw.eq(StringUtils.isNotBlank(queryBo.getFaultPart()), SysFaultInfo::getFaultPart, queryBo.getFaultPart());
        lqw.eq(StringUtils.isNotBlank(queryBo.getFaultSymptom()), SysFaultInfo::getFaultSymptom, queryBo.getFaultSymptom());

        // 故障详情模糊查询（在故障详情和备注中搜索）
        if (StringUtils.isNotBlank(queryBo.getFaultDetail())) {
            lqw.and(wrapper -> wrapper
                .like(SysFaultInfo::getFaultDetail, queryBo.getFaultDetail())
                .or()
                .like(SysFaultInfo::getRemark, queryBo.getFaultDetail())
            );
        }
        lqw.orderByDesc(SysFaultInfo::getCreateTime);
        return lqw;
    }

    /**
     * 查询故障信息列表（不分页）
     *
     * @param queryBo 查询参数
     * @return 故障信息列表
     */
    @Override
    public List<SysFaultInfoVo> queryList(SysFaultInfoQueryBo queryBo) {
        return baseMapper.selectFaultInfoWithDocList(
            queryBo.getExcavatorModel(),
            queryBo.getFaultPart(),
            queryBo.getFaultSymptom(),
            queryBo.getFaultDetail()
        );
    }

    /**
     * 查询故障信息详情
     *
     * @param faultId 故障ID
     * @return 故障信息详情
     */
    @Override
    public SysFaultInfoVo queryById(Long faultId) {
        // 优化：直接通过ID查询，避免全表扫描
        return baseMapper.selectFaultInfoWithDocById(faultId);
    }

    @Override
    public List<String> getExcavatorModelList() {
        return baseMapper.selectDistinctExcavatorModels();
    }

    @Override
    public List<String> getFaultPartList(String excavatorModel) {
        return baseMapper.selectDistinctFaultParts(excavatorModel);
    }

    @Override
    public List<String> getFaultSymptomList(String excavatorModel, String faultPart) {
        return baseMapper.selectDistinctFaultSymptoms(excavatorModel, faultPart);
    }

    @Override
    public List<Map<String, Object>> getFaultDetailList(String excavatorModel, String faultPart, String faultSymptom) {
        LambdaQueryWrapper<SysFaultInfo> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(excavatorModel), SysFaultInfo::getExcavatorModel, excavatorModel);
        lqw.eq(StringUtils.isNotBlank(faultPart), SysFaultInfo::getFaultPart, faultPart);
        lqw.eq(StringUtils.isNotBlank(faultSymptom), SysFaultInfo::getFaultSymptom, faultSymptom);
        lqw.orderByDesc(SysFaultInfo::getCreateTime);

        List<SysFaultInfo> faultInfos = baseMapper.selectList(lqw);

        return faultInfos.stream().map(fault -> {
            Map<String, Object> map = new HashMap<>();
            map.put("faultId", fault.getFaultId());
            map.put("faultDetail", fault.getFaultDetail());
            map.put("solutionId", fault.getSolutionId());
            map.put("createTime", fault.getCreateTime());
            return map;
        }).collect(Collectors.toList());
    }

    /**
     * 新增故障信息
     *
     * @param bo 故障信息
     * @return 结果
     */
    @Override
    public Boolean insertByBo(SysFaultInfoBo bo) {
        SysFaultInfo add = MapstructUtils.convert(bo, SysFaultInfo.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setFaultId(add.getFaultId());
        }
        return flag;
    }

    /**
     * 修改故障信息
     *
     * @param bo 故障信息
     * @return 结果
     */
    @Override
    public Boolean updateByBo(SysFaultInfoBo bo) {
        SysFaultInfo update = MapstructUtils.convert(bo, SysFaultInfo.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(SysFaultInfo entity) {
        // TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除故障信息
     *
     * @param ids 需要删除的故障信息主键
     * @return 结果
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            // TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SysFaultInfoVo createWithSolution(SysFaultInfoBo faultBo,
                                             MultipartFile[] files,
                                             String folderName,
                                             String remark,
                                             String action,
                                             Long linkDocId) {
        // 1) 先创建故障
        this.insertByBo(faultBo);

        // 2) 处理解决方案
        Long solutionId = null;
        if ("upload".equalsIgnoreCase(action)) {
            var docVo = solutionDocService.uploadPdfFolderSolution(files, folderName, remark);
            solutionId = docVo.getDocId();
        } else if ("link".equalsIgnoreCase(action)) {
            solutionId = linkDocId;
        }

        if (solutionId != null) {
            SysFaultInfoBo updateBo = new SysFaultInfoBo();
            updateBo.setFaultId(faultBo.getFaultId());
            updateBo.setSolutionId(solutionId);
            this.updateByBo(updateBo);
        }

        return this.queryById(faultBo.getFaultId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SysFaultInfoVo updateWithSolution(SysFaultInfoBo faultBo,
                                             MultipartFile[] files,
                                             String folderName,
                                             String remark,
                                             String action,
                                             Long linkDocId,
                                             Boolean deleteOld) {
        // 1) 更新故障基本信息
        this.updateByBo(faultBo);

        // 2) 查询当前故障，拿到旧的solutionId
        SysFaultInfoVo current = this.queryById(faultBo.getFaultId());
        Long oldSolutionId = current != null ? current.getSolutionId() : null;

        // 3) 按动作处理
        Long newSolutionId = oldSolutionId;
        if ("replace_upload".equalsIgnoreCase(action)) {
            var docVo = solutionDocService.uploadPdfFolderSolution(files, folderName, remark);
            newSolutionId = docVo.getDocId();
            // 删除旧方案（仅当未被其他故障引用，或明确要求删除）
            if (oldSolutionId != null && (Boolean.TRUE.equals(deleteOld))) {
                int ref = baseMapper.countBySolutionId(oldSolutionId);
                if (ref <= 1) {
                    // 仅此故障在用，可删除
                    solutionDocService.deleteWithValidByIds(java.util.List.of(oldSolutionId), false);
                }
            }
        } else if ("link".equalsIgnoreCase(action)) {
            newSolutionId = linkDocId;
        } else if ("remove".equalsIgnoreCase(action)) {
            newSolutionId = null;
            if (oldSolutionId != null && Boolean.TRUE.equals(deleteOld)) {
                int ref = baseMapper.countBySolutionId(oldSolutionId);
                if (ref <= 1) {
                    solutionDocService.deleteWithValidByIds(java.util.List.of(oldSolutionId), false);
                }
            }
        } // keep: 不变

        // 4) 回写新的solutionId
        SysFaultInfoBo updateBo = new SysFaultInfoBo();
        updateBo.setFaultId(faultBo.getFaultId());
        updateBo.setSolutionId(newSolutionId);
        this.updateByBo(updateBo);

        return this.queryById(faultBo.getFaultId());
    }

    // ==================== 一体化管理接口实现 ====================

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SysFaultInfoVo createFaultWithSolution(SysFaultManageBo manageBo, MultipartFile[] files) {
        // 0. 兼容性推断：当未显式提供 solutionAction 时，根据请求内容自动推断
        String inferredAction = manageBo.getSolutionAction();
        boolean hasFiles = files != null && files.length > 0;
        if (StringUtils.isBlank(inferredAction) || "none".equals(inferredAction)) {
            if (hasFiles) {
                inferredAction = "upload";
            } else if (manageBo.getLinkDocId() != null) {
                inferredAction = "link";
            } else {
                inferredAction = "none";
            }
            // 写回，复用现有 needUploadSolution/needLinkSolution 判定
            manageBo.setSolutionAction(inferredAction);
        }

        // 1. 验证参数
        if (manageBo.needUploadSolution() && (files == null || files.length == 0)) {
            throw new RuntimeException("上传解决方案时必须提供文件");
        }
        if (manageBo.needLinkSolution() && manageBo.getLinkDocId() == null) {
            throw new RuntimeException("关联解决方案时必须提供解决方案ID");
        }

        // 2. 创建故障信息
        SysFaultInfoBo faultBo = manageBo.toFaultInfoBo();
        this.insertByBo(faultBo);

        // 3. 处理解决方案
        Long solutionId = null;
        if (manageBo.needUploadSolution()) {
            // 上传新的解决方案
            SysSolutionDocVo docVo = solutionDocService.uploadPdfFolderSolution(
                files, manageBo.getSolutionFolderName(), manageBo.getSolutionRemark());
            solutionId = docVo.getDocId();
        } else if (manageBo.needLinkSolution()) {
            // 关联现有解决方案
            solutionId = manageBo.getLinkDocId();
        }

        // 4. 更新故障信息的解决方案关联
        if (solutionId != null) {
            SysFaultInfoBo updateBo = new SysFaultInfoBo();
            updateBo.setFaultId(faultBo.getFaultId());
            updateBo.setSolutionId(solutionId);
            this.updateByBo(updateBo);
        }

        // 5. 返回完整的故障信息
        return this.queryById(faultBo.getFaultId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SysFaultInfoVo updateFaultWithSolution(SysFaultManageBo manageBo, MultipartFile[] files) {
        // 1. 验证参数
        if (manageBo.getFaultId() == null) {
            throw new RuntimeException("更新时故障ID不能为空");
        }
        if (manageBo.needUploadSolution() && (files == null || files.length == 0)) {
            throw new RuntimeException("上传解决方案时必须提供文件");
        }
        if (manageBo.needLinkSolution() && manageBo.getLinkDocId() == null) {
            throw new RuntimeException("关联解决方案时必须提供解决方案ID");
        }

        // 2. 查询当前故障信息
        SysFaultInfoVo currentFault = this.queryById(manageBo.getFaultId());
        if (currentFault == null) {
            throw new RuntimeException("故障信息不存在");
        }
        Long oldSolutionId = currentFault.getSolutionId();

        // 3. 更新故障基本信息
        SysFaultInfoBo faultBo = manageBo.toFaultInfoBo();
        this.updateByBo(faultBo);

        // 4. 处理解决方案
        Long newSolutionId = oldSolutionId;

        if ("replace_upload".equals(manageBo.getSolutionAction())) {
            // 替换上传新的解决方案
            SysSolutionDocVo docVo = solutionDocService.uploadPdfFolderSolution(
                files, manageBo.getSolutionFolderName(), manageBo.getSolutionRemark());
            newSolutionId = docVo.getDocId();

            // 删除旧解决方案（如果需要且没有其他引用）
            if (oldSolutionId != null && Boolean.TRUE.equals(manageBo.getDeleteOldSolution())) {
                deleteSolutionIfNotReferenced(oldSolutionId, manageBo.getFaultId());
            }
        } else if (manageBo.needLinkSolution()) {
            // 关联现有解决方案
            newSolutionId = manageBo.getLinkDocId();
            
            // 删除旧解决方案（如果需要且没有其他引用）
            if (oldSolutionId != null && Boolean.TRUE.equals(manageBo.getDeleteOldSolution())) {
                deleteSolutionIfNotReferenced(oldSolutionId, manageBo.getFaultId());
            }
        } else if (manageBo.needRemoveSolution()) {
            // 移除解决方案关联
            newSolutionId = null;
            
            // 删除旧解决方案（如果需要且没有其他引用）
            if (oldSolutionId != null && Boolean.TRUE.equals(manageBo.getDeleteOldSolution())) {
                deleteSolutionIfNotReferenced(oldSolutionId, manageBo.getFaultId());
            }
        }
        // keepSolution() 或 "none": 保持不变

        // 5. 更新解决方案关联
        SysFaultInfoBo updateBo = new SysFaultInfoBo();
        updateBo.setFaultId(manageBo.getFaultId());
        updateBo.setSolutionId(newSolutionId);
        this.updateByBo(updateBo);

        // 6. 返回完整的故障信息
        return this.queryById(manageBo.getFaultId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteFaultWithCascade(Collection<Long> ids, String cascadeStrategy) {
        // 处理每个故障的解决方案
        for (Long id : ids) {
            SysFaultInfoVo vo = this.queryById(id);
            Long solutionId = vo != null ? vo.getSolutionId() : null;
            
            if (solutionId != null) {
                boolean shouldDelete = "yes".equalsIgnoreCase(cascadeStrategy)
                    || ("auto".equalsIgnoreCase(cascadeStrategy) && 
                        baseMapper.countBySolutionId(solutionId) <= 1);
                
                if (shouldDelete) {
                    solutionDocService.deleteWithValidByIds(java.util.List.of(solutionId), false);
                }
            }
        }
        
        // 删除故障信息
        return this.deleteWithValidByIds(ids, false);
    }

    /**
     * 删除解决方案（如果没有其他故障引用）
     */
    private void deleteSolutionIfNotReferenced(Long solutionId, Long excludeFaultId) {
        if (solutionId == null) return;
        
        int refCount = baseMapper.countBySolutionId(solutionId);
        // 如果只有当前故障引用，则可以删除
        if (refCount <= 1) {
            solutionDocService.deleteWithValidByIds(java.util.List.of(solutionId), false);
        }
    }

    // ==================== 兼容性方法实现 ====================

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithCascade(Collection<Long> ids, String cascadeStrategy) {
        return deleteFaultWithCascade(ids, cascadeStrategy);
    }
}
